//------------------------------------------------------------------------------------------------------
//   _____     _______ ____  _     ___  ____  ____    _____ _   _  ____ ___ _   _ _____   ______  ___ _ 
//  / _ \ \   / / ____|  _ \| |   / _ \|  _ \|  _ \  | ____| \ | |/ ___|_ _| \ | | ____| |  _ \ \/ / / |
// | | | \ \ / /|  _| | |_) | |  | | | | |_) | | | | |  _| |  \| | |  _ | ||  \| |  _|   | | | \  /| | |
// | |_| |\ V / | |___|  _ <| |__| |_| |  _ <| |_| | | |___| |\  | |_| || || |\  | |___  | |_| /  \| | |
//  \___/  \_/  |_____|_| \_\_____\___/|_| \_\____/  |_____|_| \_|\____|___|_| \_|_____| |____/_/\_\_|_|
//
// Overlord Engine v1.82
// Copyright Overlord Thomas Goussaert & Overlord Brecht Kets
// http://www.digitalartsandentertainment.com/
//------------------------------------------------------------------------------------------------------
//Precompiled Header [ALWAYS ON TOP IN CPP]
#include "Base\stdafx.h"

#include "UberMaterial.h"
#include "Base/GeneralStructs.h"
#include "Diagnostics/Logger.h"
#include "Content/ContentManager.h"
#include "Graphics/TextureData.h"

ID3DX11EffectShaderResourceVariable* UberMaterial::m_pDiffuseSRVvariable = nullptr;
ID3DX11EffectShaderResourceVariable* UberMaterial::m_pSpecularSRVvariable = nullptr;
ID3DX11EffectShaderResourceVariable* UberMaterial::m_pNormalMapSRVvariable = nullptr;
ID3DX11EffectShaderResourceVariable* UberMaterial::m_pEnvironmentSRVvariable = nullptr;
ID3DX11EffectShaderResourceVariable* UberMaterial::m_pOpacitySRVvariable = nullptr;
 
ID3DX11EffectScalarVariable* UberMaterial::m_pDiffuseSBoolvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pSpecularSBoolvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pNormalMapSBoolvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pEnvironmentSBoolvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pReflectionStrengthSFloatvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pOpacitySBoolvariable = nullptr;

ID3DX11EffectScalarVariable* UberMaterial::m_pRefractionStrengthSFloatvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pOpacitySFloatvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pRefractionIndexSFloatvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pAmbientIntensitySFloatvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pFresnelPowerSFloatvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pFresnelMultiplierSFloatvariable = nullptr;

ID3DX11EffectScalarVariable* UberMaterial::m_pFresnelFallOffSBoolvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pFlipGreenChannelSBoolvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pSpecularBlinnSBoolvariable = nullptr;
ID3DX11EffectScalarVariable* UberMaterial::m_pSpecularPhongSBoolvariable = nullptr;

UberMaterial::UberMaterial() : Material(L"./Resources/Effects/UberShader.fx"),
	m_pDiffuseTexture(nullptr),
	m_pSpecularTexture(nullptr),
	m_pNormalMapTexture(nullptr),
	m_pEnvironmentMapTexture(nullptr),
	m_TextureOpacity(nullptr),
	m_bDiffuseTexture(false),
	m_bSpecularTexture(false),
	m_bNormalMapTexture(false),
	m_bEnvironmentMapTexture(false),
	m_ReflectionStrength(0.0f),
	m_bOpacityMap(false),
	m_RefractionStrength(0),
	m_RefractionIndex(0.3f),
	m_Opacity(1),
	m_AmbientIntensity(0),
	m_FresnelPower(1),
	m_FresnelMultiplier(1),
	m_Shininess(15),
	m_SpecularBlinn(false),
	m_SpecularPhong(false),
	m_bFresnelFallOff(false),
	m_FlipGreenChannel(false)
{

}


UberMaterial::~UberMaterial()
{

}

void UberMaterial::SetDiffuseTexture(const wstring& assetFile)
{
	m_pDiffuseTexture = ContentManager::Load<TextureData>(assetFile);
	m_bDiffuseTexture = true;
}

void UberMaterial::SetSpecularTexture(const wstring& assetFile)
{
	m_pSpecularTexture = ContentManager::Load<TextureData>(assetFile);
	m_bSpecularTexture = true;
}

void UberMaterial::SetNormalMapTexture(const wstring& assetFile)
{
	m_pNormalMapTexture = ContentManager::Load<TextureData>(assetFile);
	m_bNormalMapTexture = true;
}

void UberMaterial::SetEnvironmentMapTexture(const wstring& assetFile)
{
	m_pEnvironmentMapTexture = ContentManager::Load<TextureData>(assetFile);
	m_bEnvironmentMapTexture = true;
}

void UberMaterial::SetReflectionStrength(float amount)
{
	m_ReflectionStrength = amount;
}

void UberMaterial::SetOpacityMap(const wstring& assetFile)
{
	m_TextureOpacity = ContentManager::Load<TextureData>(assetFile);
	m_bOpacityMap = true;
}

void UberMaterial::SetRefractionStrength(float amount)
{
	m_RefractionStrength = amount;
}

void UberMaterial::SetRefractionIndex(float amount)
{
	m_RefractionIndex = amount;
}

void UberMaterial::SetOpacity(float amount)
{
	m_bOpacityMap = true;
	m_Opacity = amount;
}

void UberMaterial::SetAmbientIntensity(float amount)
{
	m_AmbientIntensity = amount;
}

void UberMaterial::SetFresnelPower(float amount)
{
	m_FresnelPower = amount;
}

void UberMaterial::SetFresnelMultiplier(float amount)
{
	m_FresnelMultiplier = amount;
}

void UberMaterial::SetShininess(int amount)
{
	m_Shininess = amount;
}

void UberMaterial::SetFresnelFallOff(bool b)
{
	m_bFresnelFallOff = b;
}

void UberMaterial::FlipGreenChannel(bool flip)
{
	m_FlipGreenChannel = flip;
}

void UberMaterial::SetSpecularBlinn(bool b)
{
	m_SpecularBlinn = b;
}

void UberMaterial::SetSpecularPhong(bool b)
{
	m_SpecularPhong = b;
}

void UberMaterial::LoadEffectVariables()
{
	if (!m_pDiffuseSRVvariable)
	{
		m_pDiffuseSRVvariable = m_pEffect->GetVariableByName("m_TextureDiffuse")->AsShaderResource();
		m_pDiffuseSBoolvariable = m_pEffect->GetVariableByName("m_bDiffuseTexture")->AsScalar();
		if (!m_pDiffuseSRVvariable->IsValid())
		{
			Logger::LogWarning(L"DiffuseMaterial::LoadEffectVariables() > \'m_TextureDiffuse\' variable not found!");
			m_pDiffuseSRVvariable = nullptr;
		}
	}

	if (!m_pSpecularSRVvariable)
	{
		m_pSpecularSRVvariable = m_pEffect->GetVariableByName("m_TextureSpecularLevel")->AsShaderResource();
		m_pSpecularSBoolvariable = m_pEffect->GetVariableByName("m_bSpecularLevelTexture")->AsScalar();
		if (!m_pSpecularSRVvariable->IsValid())
		{
			Logger::LogWarning(L"DiffuseMaterial::LoadEffectVariables() > \'m_TextureSpecularLevel\' variable not found!");
			m_pSpecularSRVvariable = nullptr;
		}
	}

	if (!m_pNormalMapSRVvariable)
	{
		m_pNormalMapSRVvariable = m_pEffect->GetVariableByName("m_TextureNormal")->AsShaderResource();
		m_pNormalMapSBoolvariable = m_pEffect->GetVariableByName("m_bNormalMapping")->AsScalar();
		if (!m_pNormalMapSRVvariable->IsValid())
		{
			Logger::LogWarning(L"DiffuseMaterial::LoadEffectVariables() > \'m_TextureNormal\' variable not found!");
			m_pNormalMapSRVvariable = nullptr;
		}
	}

	if (!m_pEnvironmentSRVvariable)
	{
		m_pEnvironmentSRVvariable = m_pEffect->GetVariableByName("m_CubeEnvironment")->AsShaderResource();
		m_pEnvironmentSBoolvariable = m_pEffect->GetVariableByName("m_bEnvironmentMapping")->AsScalar();
		m_pReflectionStrengthSFloatvariable = m_pEffect->GetVariableByName("m_ReflectionStrength")->AsScalar();
		if (!m_pEnvironmentSRVvariable->IsValid())
		{
			Logger::LogWarning(L"DiffuseMaterial::LoadEffectVariables() > \'m_CubeEnvironment\' variable not found!");
			m_pEnvironmentSRVvariable = nullptr;
		}
	}

	if (!m_pOpacitySRVvariable)
	{
		m_pOpacitySRVvariable = m_pEffect->GetVariableByName("m_TextureOpacity")->AsShaderResource();
		m_pOpacitySBoolvariable = m_pEffect->GetVariableByName("m_bOpacityMap")->AsScalar();
		m_pOpacitySFloatvariable  = m_pEffect->GetVariableByName("m_Opacity")->AsScalar();
		if (!m_pEnvironmentSRVvariable->IsValid())
		{
			Logger::LogWarning(L"DiffuseMaterial::LoadEffectVariables() > \'m_TextureOpacity\' variable not found!");
			m_pOpacitySRVvariable = nullptr;
		}
	}

	if (!m_pSpecularBlinnSBoolvariable)
	{
		m_pSpecularBlinnSBoolvariable = m_pEffect->GetVariableByName("m_SpecularBlinn")->AsScalar();
	}

	if (!m_pSpecularPhongSBoolvariable)
	{
		m_pSpecularPhongSBoolvariable = m_pEffect->GetVariableByName("m_SpecularPhong")->AsScalar();
	}
	
	if (!m_pFresnelFallOffSBoolvariable)
	{
		m_pFresnelFallOffSBoolvariable = m_pEffect->GetVariableByName("m_bFresnelFallOff")->AsScalar();
	}

//m_pRefractionStrengthSFloatvariable = nullptr;
//m_pOpacitySFloatvariable = nullptr;
//m_pRefractionIndexSFloatvariable = nullptr;
//m_pAmbientIntensitySFloatvariable = nullptr;
//m_pFresnelPowerSFloatvariable = nullptr;
//m_pFresnelMultiplierSFloatvariable = nullptr;
//m_pFlipGreenChannelSBoolvariable = nullptr;
}

void UberMaterial::UpdateEffectVariables(const GameContext& gameContext, ModelComponent* pModelComponent)
{
	UNREFERENCED_PARAMETER(gameContext);
	UNREFERENCED_PARAMETER(pModelComponent);

	if (m_pDiffuseTexture && m_pDiffuseSRVvariable)
	{
		m_pDiffuseSRVvariable->SetResource(m_pDiffuseTexture->GetShaderResourceView());
		m_pDiffuseSBoolvariable->SetBool(m_bDiffuseTexture);
	}

	if (m_pSpecularTexture && m_pSpecularSRVvariable)
	{
		m_pSpecularSRVvariable->SetResource(m_pSpecularTexture->GetShaderResourceView());
		m_pSpecularSBoolvariable->SetBool(m_bSpecularTexture);
	}

	if (m_pNormalMapTexture && m_pNormalMapSRVvariable)
	{
		m_pNormalMapSRVvariable->SetResource(m_pNormalMapTexture->GetShaderResourceView());
		m_pNormalMapSBoolvariable->SetBool(m_bNormalMapTexture);
	}

	if (m_pEnvironmentMapTexture && m_pEnvironmentSRVvariable)
	{
		m_pEnvironmentSRVvariable->SetResource(m_pEnvironmentMapTexture->GetShaderResourceView());
		m_pEnvironmentSBoolvariable->SetBool(m_bEnvironmentMapTexture);
		m_pReflectionStrengthSFloatvariable->SetFloat(m_ReflectionStrength);
	}

	if (m_TextureOpacity && m_pOpacitySRVvariable)
	{
		m_pEnvironmentSRVvariable->SetResource(m_TextureOpacity->GetShaderResourceView());
		m_pEnvironmentSBoolvariable->SetBool(m_bOpacityMap);
		//m_pReflectionStrengthSFloatvariable->SetFloat(m_ReflectionStrength);
	}

	if (m_bOpacityMap)
	{
		m_pEnvironmentSBoolvariable->SetBool(m_bOpacityMap);
		m_pOpacitySFloatvariable->SetFloat(m_Opacity);
	}

	if (m_SpecularBlinn)
	{
		m_pSpecularBlinnSBoolvariable->SetBool(m_SpecularBlinn);
	}

	if (m_SpecularPhong)
	{
		m_pSpecularPhongSBoolvariable->SetBool(m_SpecularPhong);
	}

	if (m_bFresnelFallOff)
	{
		m_pFresnelFallOffSBoolvariable->SetBool(m_bFresnelFallOff);
	}

}
